package tiers2;

import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.jws.WebMethod;
import javax.jws.WebService;

import tiers3.services.IServicePersistance;
import common.Tweet;
import common.Utilisateur;

@WebService
public class ServiceMetier {
	
	@WebMethod
	/**
	 * Créer un nouvel utilisateur en fonction des paramètres passés
	 */
	public Utilisateur creerCompte(String nom, String prenom, String email,
			String login, String mdp) throws AccessException, RemoteException,
			NotBoundException {
		// Création de l'utilisateur
		Utilisateur utilisateur = new Utilisateur(nom, prenom, email, login, mdp);
		// Persistence en base
		return getServicePersistance().creerUtilisateur(utilisateur);
	}

	@WebMethod
	/**
	 * Connecte un utilisateur à l'application
	 */
	public Utilisateur authentifier(String login, String mdp) throws AccessException, RemoteException, NotBoundException {
		// Recherche si l'utilisateur répondant au couple login/mdp existe en base
		return getServicePersistance().rechercherUtilisateurParLoginMdp(login, mdp);
	}

	@WebMethod
	/**
	 * Déconnecte un utilisateur de l'application
	 */
	public boolean deconnecter() {
		return true;
	}

	@WebMethod
	/**
	 * Recherche l'ensemble des utilisateurs de l'application
	 */
	public List<Utilisateur> listerUtilisateurs() throws AccessException, RemoteException, NotBoundException {
		// Recherche de tous les utilisateurs existants en base
		return getServicePersistance().rechercherTousUtilisateurs();
	}

	@WebMethod
	/**
	 * Abonne l'utilisateur à un autre dont l'id est passé en paramètre
	 */
	public void abonner(Utilisateur utilisateur, int abonneId) throws AccessException, RemoteException, NotBoundException {
		// Ajout d'un abonnement utilisateur et persistance
		getServicePersistance().ajoutSuivi(utilisateur, abonneId);
	}

	@WebMethod
	/**
	 * Désabonne l'utilisateur d'un autre utilisateur dont l'id est passé en paramètre
	 */
	public void desabonner(Utilisateur utilisateur, int abonneId) throws AccessException, RemoteException, NotBoundException {
		// Suppression d'un abonnement utilisateur et persistance
		getServicePersistance().supprimerSuivi(utilisateur, abonneId);
	}

	@WebMethod
	/**
	 * Renvoie l'ensemble des tweets de l'ensemble des utilisateurs dont notre utilisateur est abonné
	 */
	public List<Tweet> listerTweetsDesUtilisateursSuivis(Utilisateur utilisateur) throws AccessException, RemoteException, NotBoundException {
		// Renvoyer les utilisateurs suivis pour un id d'utilisateur
		List<Tweet> listeTweetsSuivis = new ArrayList<Tweet>();
		for (Integer userId :  getServicePersistance().rechercherUtilisateurParId(utilisateur.getId()).getListeUtilisateurs()) {
			listeTweetsSuivis.addAll(getServicePersistance().rechercherUtilisateurParId(userId).getListeTweets());
		}
		// Tri par date
		Collections.sort(listeTweetsSuivis);
		// Renvoie la liste des tweets
		return listeTweetsSuivis;
	}

	@WebMethod
	/**
	 * Créer un tweet pour l'utilisateur courant
	 */
	public Tweet envoyerTweet(Integer idUtilisateur, String msgUtilisateur) throws AccessException, RemoteException, NotBoundException {
		// Récupération de l'utilisateur par son id
		Utilisateur monUser = getServicePersistance().rechercherUtilisateurParId(idUtilisateur);
		// Création d'un nouveau tweet ayant pour corp msgUtilisateur
		Tweet monTweet = new Tweet(idUtilisateur, msgUtilisateur);
		// Création du tweet et persistance en base
		return getServicePersistance().creerTweet(monUser, monTweet);
	}
	
	@WebMethod
	/**
	 * Supprimer un tweet pour l'utilisateur courant
	 */
	public boolean suppressionTweet(Utilisateur utilisateur, Tweet tweet) throws AccessException, RemoteException, NotBoundException{
		return getServicePersistance().supprimerTweet(utilisateur, tweet);
	}

	@WebMethod
	/**
	 * Affiche le profil d'un utilisateur dont l'id est passé en paramètre
	 */
	public String afficherProfil(Integer idUtilisateur) throws AccessException, RemoteException, NotBoundException {
		StringBuffer sb = new StringBuffer();
		// Récupération de l'utilisateur par son id
		Utilisateur monUtilisateur = getServicePersistance().rechercherUtilisateurParId(idUtilisateur);
		Utilisateur monSuivis;
		// Affichage des information utilisateur
		sb.append("\nNom: "+monUtilisateur.getNom()+"\n"
				+"Prenom: "+monUtilisateur.getPrenom()+"\n"
				+"Mail: "+monUtilisateur.getMail()+"\n");
		// Affichage de la liste de utilisateurs suivis
		sb.append("\n###### Abonnements ######\n");
		for(Integer id : monUtilisateur.getListeUtilisateurs()){
			monSuivis = getServicePersistance().rechercherUtilisateurParId(id);
			sb.append("\n" + monSuivis.getNom()+" "+monSuivis.getPrenom() + "\n");
		}
		
		// Tri des tweets par date
		List<Tweet> listeTweetUtilisateur = monUtilisateur.getListeTweets();
		Collections.sort(listeTweetUtilisateur);
		
		// Affichage de la liste des tweets postés par l'utilisateur
		sb.append("\n###### Tweets postés ######\n");
		for(Tweet monTweet : listeTweetUtilisateur){
			sb.append("\n---"+monTweet.getDate()+"---\n");
			sb.append("  " + monTweet.getContenu() + "\n");
		}
		// Renvoie l'affichage du profil
		return sb.toString();
	}
	
	@WebMethod
	/**
	 * Recherche la liste des utilisateurs correspondant au nom passé en paramètre
	 */
	public List<Utilisateur> listerUtilisateurRechercheNom(String pNom) throws AccessException, RemoteException, NotBoundException{
		return getServicePersistance().rechercherUtilisateursParNom(pNom);
	}
	
	@WebMethod
	/**
	 * Recherche un utilisateur correspondant au login passé en paramètre
	 */
	public Utilisateur rechercheUtilisateurParLogin(String pLogin) throws AccessException, RemoteException, NotBoundException{
		return getServicePersistance().rechercherUtilisateurParLogin(pLogin);
	}
	
	@WebMethod
	/**
	 * Rechercher la liste des tweets d'un utilisateur
	 */
	public List<Tweet> listeTweetUtilisateur(Utilisateur utilisateur) throws AccessException, RemoteException, NotBoundException{
		return getServicePersistance().rechercherTweetsParUtilisateur(utilisateur);
	}

	/**
	 * Donne les informations sur le serveur distant à écouté
	 */
	private IServicePersistance getServicePersistance() throws AccessException, RemoteException, NotBoundException {
		Registry registry = LocateRegistry.getRegistry("127.0.0.1", 2000);
		IServicePersistance service;
		service = (IServicePersistance) registry.lookup("ServicePersistance");
		return service;
	}
}
